package com.wmyg.antifake.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.rabbitmq.client.AMQP;
import com.wmyg.antifake.bean.FactoryBean;
import com.wmyg.antifake.bean.FactorySumInfo;
import com.wmyg.antifake.bean.QRInfo;
import com.wmyg.antifake.bean.QueryInfo;
import com.wmyg.antifake.dao.BillMapper;
import com.wmyg.antifake.dao.FabricDao;
import com.wmyg.antifake.message.TrackApplyMessage;
import com.wmyg.antifake.message.TrackMessage;
import com.wmyg.antifake.sdk.FabricException;
import com.wmyg.antifake.service.AsyncTaskService;
import com.wmyg.antifake.service.FabricService;
import com.wmyg.antifake.utils.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.hyperledger.fabric.sdk.exception.ProposalException;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.MessagePropertiesConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.websocket.Session;
import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeoutException;

@Slf4j
@Service
public class AsyncTaskServiceImpl implements AsyncTaskService {

    @Autowired
    BillMapper billDao;

    @Autowired
    WebSocketServer webSocketServer;

    @Autowired
    FabricDao fabricDao;

    @Autowired
    MessagePropertiesConverter messagePropertiesConverter;

    @Autowired
    RabbitTemplate rabbitTemplate;

    //TODO 厂家总数
    @Async("asyncBillInsert")
    public void selectFactorySumCountAsync(int factoryId, Session session) {
        comPubMent1(session,factoryId,1);
    }

    //TODO 生产线总数
    @Async("asyncBillInsert")
    public void selectDeviceInfoCountAsync(int factoryId, Session session) {
        comPubMent1(session,factoryId,2);
    }


    //TODO 厂商二维码总数
    @Async("asyncMoveDataToRedis")
    public void selectFactoryByIdSum (int factorId ,Session session) {
       log.info("线程名称:-------------"+Thread.currentThread().getName());
        try {
            while (true){
                List<FactorySumInfo> deviceList = null;
                deviceList = billDao.selectFactoryByIdSum(factorId);
                if(session == null){
                    webSocketServer.onClose();
                    break;
                }
                if(deviceList.size()==0){
                    continue;
                }
                Long sumCase = 0L;
                for(FactorySumInfo list:deviceList){
                    list.setTotalNum(list.getCaseNum()+list.getBoxNum()+list.getPackageNum());
                    sumCase = list.getTotalNum()+sumCase;
                }
                deviceList.get(0).setSumCase(sumCase);
                String obj = JSONArray.toJSON(deviceList).toString();
                session.getBasicRemote().sendText(obj);
                Thread.sleep(3000);
                log.info(obj);
            }
        } catch (Exception e) {
            log.info("断开连接了1");
           try{
               webSocketServer.onClose();
           }catch (Exception e1){
               log.info("断开连接了2");
           }
        }
    }

    @Async(value = "asyncMoveDataToRedis")
    public void syncDataFabricAndRedis(String qR, QueryInfo queryInfo) {
        try {
//            QRInfo q = fabricDao.query(qR, queryInfo);
            QRInfo q = sendTrackMessage(qR, queryInfo);
            //q.getQueryHistory().add(queryInfo);
            //redisTemplate.opsForValue().set(qR, q);
            log.info("querytimes async get for fabric is {}>>>>>>>>>>>>>>>>>>>>>>>>>", q.getQueryHistory().size());
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }


    @Async("asyncDataPrepare")
    public void selectCaseIdCountAsync(int factoryId, Session session) {
        comPubMent2(session,factoryId);
    }


    private void comPubMent1(Session session,int factoryId,int isDevCount){
        log.info("线程名称:-------------"+Thread.currentThread().getName());
        try {
            while (true){
                List<FactoryBean> deviceList = null;
                if(isDevCount == 1){
                    deviceList= billDao.selectFactoryCountSum(factoryId);
                }else if(isDevCount == 2){
                    deviceList= billDao.selectDeviceInfoCount(factoryId);
                }
                if(session == null){
                    webSocketServer.onClose();
                    break;
                }
                if(deviceList.size()==0){
                    continue;
                }
                if(isDevCount == 1 && factoryId == 0){
                    int successNum  = 0;
                    //TODO 平台总数
                    for(FactoryBean list:deviceList){
                        successNum = successNum+list.getSuccessNum();
                    }
                    deviceList = this.setFactoryBean(successNum);
                }
                String obj = JSONArray.toJSON(deviceList).toString();
                session.getBasicRemote().sendText(obj);
                Thread.sleep(3000);
                log.info(obj);

            }
        } catch (Exception e) {
            log.info("断开连接了1");
            try{
                webSocketServer.onClose();
            }catch (Exception e1){
                log.info("断开连接了2");
            }
        }
    }



    private void comPubMent2(Session session,int factoryId){
        String caseIdMax = "";
        log.info("线程名称:-------------"+Thread.currentThread().getName());
        try {
            while (true){
                List<FactoryBean> CaseList = null;
                CaseList = billDao.selectFactorycaseIdCount(factoryId);
                if(session == null ){
                    webSocketServer.onClose();
                    break;
                }
                if(CaseList.size()==0){
                    continue;
                }
                if(!caseIdMax .equals(CaseList.get(0).getCaseId())){
                    caseIdMax = CaseList.get(0).getCaseId();
                    String obj = JSONArray.toJSON(CaseList).toString();
                    session.getBasicRemote().sendText(obj);
                    Thread.sleep(1000);
                    log.info(obj);
                }

            }
        } catch (Exception e) {
            log.info("断开连接了1");
            try{
                webSocketServer.onClose();
            }catch (Exception e1){
                log.info("断开连接了2");
            }
        }
    }

    private List<FactoryBean> setFactoryBean(int successNum){
        List<FactoryBean> FactoryBeanList = new ArrayList<FactoryBean>();
        FactoryBean factoryBean = new FactoryBean();
        factoryBean.setFactoryName("微盟云谷平台");
        SimpleDateFormat f=new SimpleDateFormat();
        factoryBean.setTimes(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+".0");
        factoryBean.setSuccessNum(successNum);
        FactoryBeanList.add(factoryBean);
        return FactoryBeanList;
    }

    @Override
    public QRInfo sendTrackMessage(String qR, QueryInfo queryInfo) throws Throwable {
        String correlationId = UUID.randomUUID().toString();
        Date sendTime = new Date();
        AMQP.BasicProperties props =
                new AMQP.BasicProperties("text/plain",
                        "UTF-8",
                        null,
                        2,
                        0, correlationId, "trackReplyMessageExchange", null,
                        null, sendTime, null, null,
                        "TrackProducer", null);


        MessageProperties sendMessageProperties =
                messagePropertiesConverter.toMessageProperties(props, null,"UTF-8");
        sendMessageProperties.setReceivedExchange("trackReplyMessageExchange");
        sendMessageProperties.setReceivedRoutingKey("trackReplyMessage");
        sendMessageProperties.setRedelivered(true);

        TrackMessage trackMessage = new TrackMessage();
        trackMessage.setQR(qR);
        trackMessage.setQueryInfo(queryInfo);
        String message = JSON.toJSONString(trackMessage);


        org.springframework.amqp.core.Message sendMessage = MessageBuilder.withBody(message.getBytes("UTF-8"))
                .andProperties(sendMessageProperties)
                .build();
        org.springframework.amqp.core.Message replyMessage = rabbitTemplate.sendAndReceive("trackMessageExchange",
                "trackMessage", sendMessage);

        String replyMessageContent = null;
        if (null == replyMessage) {
            throw new TimeoutException();
        }
        replyMessageContent = new String(replyMessage.getBody(),"UTF-8");
        log.info("Receive the apply from tracker {}", replyMessageContent);
        TrackApplyMessage trackApplyMessage = JSON.parseObject(replyMessageContent, TrackApplyMessage.class);
        if (trackApplyMessage.getExceptionCode() != 0) {
            switch (trackApplyMessage.getExceptionCode()) {
                case 1:
                    throw new FileNotFoundException();
                case 2:
                    throw new ProposalException(trackApplyMessage.getExceptionMessage());
                case 3:
                    throw new TimeoutException();
                case 4:
                    throw new FabricException(trackApplyMessage.getExceptionMessage());
                case 5:
                    throw new Exception("查询失败：此二维码正在被查询");
                case 6:
                    throw new Throwable(trackApplyMessage.getExceptionMessage());
                default:
                    break;
            }
        }

        return trackApplyMessage.getQrInfo();
    }

}
